package com.xhwl.centiotdata.controller;

import com.xhwl.centiotdata.pollingtrigger.pedestrian.PedestrianDispatcher;
import com.xhwl.centiotdata.repair.PedestriansSyncManager;
import com.xhwl.centiotdata.service.RepairDetailLogService;
import com.xhwl.centiotdata.service.RepairOperateLogService;
import com.xhwl.centiotdata.service.RepairScopeConfigService;
import com.xhwl.centiotdata.service.integrateconfig.PedestrianIntegrationConfig;
import com.xhwl.common.dto.cent.iotdata.repair.RepairActionDTO;
import com.xhwl.common.dto.cent.iotdata.repair.RepairDetailDTO;
import com.xhwl.common.enums.CodeEnum;
import com.xhwl.common.enums.iot.RepairResultEnum;
import com.xhwl.common.enums.iot.RepairStepResultEnum;
import com.xhwl.common.enums.iot.RepairTypeEnum;
import com.xhwl.common.pojo.ResultJson;
import com.xhwl.common.pojo.cent.iot.RepairDetailLog;
import com.xhwl.common.pojo.cent.iot.RepairOperateLog;
import com.xhwl.common.pojo.cent.iot.RepairScopeConfig;
import com.xhwl.common.pojo.cent.sdata.Account;
import com.xhwl.common.query.cent.iotdata.RepairLogQuery;
import com.xhwl.common.utils.CalendarUtil;
import com.xhwl.common.utils.ResponseUtil;
import com.xhwl.common.utils.StringUtils;
import com.xhwl.common.utils.excel.ExcelUtils;
import com.xhwl.common.vo.cent.iot.PageSimpleVO;
import com.xhwl.common.vo.cent.iot.RepairScopeVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

import static com.xhwl.common.dto.cent.iotdata.repair.RepairActionDTO.getDefaultDatePattern;

/**
 * 数据补救接口
 * <p>
 * <p>
 * Copyright (C),1998-2022, 兴海物联
 * FileName: FetchDataController
 * Author: XuChang
 * Date: 2022/5/27 11:02
 * Description: 数据补救接口
 * History:
 */
@RestController
@RequestMapping("/repair")
public class RepairDataController {

    PedestrianDispatcher pedestrianDispatcher;

    RepairOperateLogService repairOperateLogService;

    RepairDetailLogService repairDetailLogService;

    PedestrianIntegrationConfig integrationConfig;

    PedestriansSyncManager pedestriansSyncManager;

    RepairScopeConfigService repairScopeConfigService;

    @Autowired
    public void setPedestrianDispatcher(PedestrianDispatcher pedestrianDispatcher) {
        this.pedestrianDispatcher = pedestrianDispatcher;
    }

    @Autowired
    public void setRepairOperateLogService(RepairOperateLogService repairOperateLogService) {
        this.repairOperateLogService = repairOperateLogService;
    }

    @Autowired
    public void setRepairDetailLogService(RepairDetailLogService repairDetailLogService) {
        this.repairDetailLogService = repairDetailLogService;
    }

    @Autowired
    public void setIntegrationConfig(PedestrianIntegrationConfig integrationConfig) {
        this.integrationConfig = integrationConfig;
    }

    @Autowired
    public void setPedestriansSyncManager(PedestriansSyncManager pedestriansSyncManager) {
        this.pedestriansSyncManager = pedestriansSyncManager;
    }

    @Autowired
    public void setRepairScopeConfigService(RepairScopeConfigService repairScopeConfigService) {
        this.repairScopeConfigService = repairScopeConfigService;
    }

    /**
     * 获取某个项目下的补救范围，和可选择的补救类型
     *
     * @param projectId 项目id
     */
    @GetMapping(value = "/scope")
    public ResultJson<List<RepairScopeVO>> getScope(@RequestParam("projectId") Integer projectId) {
        List<RepairScopeConfig> config = repairScopeConfigService.getConfig(projectId);
        if (CollectionUtils.isEmpty(config))
            return ResultJson.fail(CodeEnum.EXCEL_IMPORT_CHECK_FAIL);
        List<RepairScopeVO> list = new ArrayList<>();
        config.stream().forEach(repairConfigBean -> {
            list.add(generateScope(repairConfigBean.getRepairType(), projectId, repairConfigBean.getBeginTime(), repairConfigBean.getEndTime()));
        });
        return ResultJson.success(list);
    }

    private RepairScopeVO generateScope(int type, int projectId, Date beginTime, Date endTime) {
        RepairScopeVO repairScopeVO = new RepairScopeVO();
        repairScopeVO.setProjectId(projectId);
        repairScopeVO.setRepairType(type);
        repairScopeVO.setDateBegin(CalendarUtil.getDateStr(CalendarUtil.DATE_FORMAT[1], beginTime));
        if (endTime == null) {
            //截至时间是昨天
            repairScopeVO.setDateEnd(CalendarUtil.getLastDateFormat());
        } else {
            repairScopeVO.setDateEnd(CalendarUtil.getDateStr(CalendarUtil.DATE_FORMAT[1], endTime));
        }
        RepairTypeEnum repairTypeEnum = RepairTypeEnum.getType(type);
        if (repairTypeEnum != null) {
            repairScopeVO.setTypeDesc(repairTypeEnum.getDesc());
        }
        return repairScopeVO;
    }

    /**
     * 修复操作
     *
     * @param repairActionDTO
     * @param account
     * @return
     */
    @PostMapping(value = "/action")
    public ResultJson action(@RequestBody @Valid RepairActionDTO repairActionDTO, Account account) {
        if (account == null) {
            return ResultJson.fail("未获取到操作人信息");
        }
        if (!isCorrectDate(repairActionDTO.getStartDate()) || !isCorrectDate(repairActionDTO.getEndDate())) {
            return ResultJson.fail("请传入正确的时间格式," + getDefaultDatePattern());
        }
        //检查传入的范围是否在配置范围内
        boolean legalScope = repairScopeConfigService.isLegalScope(repairActionDTO);
        if (!legalScope) {
            return ResultJson.fail("当前时间范围不支持恢复数据");
        }
        //检查有没有同类的任务正在执行
        if (repairOperateLogService.isRepairInvoking(repairActionDTO)) {
            return ResultJson.fail("当前有正在执行的任务，请等待完成后重试");
        }
        //执行动作
        String errorMsg = pedestriansSyncManager.start(repairActionDTO.getOperateType(), repairActionDTO, account);
        if (StringUtils.isNotEmpty(errorMsg)) {
            return ResultJson.fail(errorMsg);
        }
        return ResultJson.success("任务开启成功，执行中。");
    }

    /**
     * 修改某个操作为失败
     *
     * @param operateId
     * @return
     */
    @GetMapping(value = "/failed")
    public ResultJson failedOperate(@RequestParam("operateId") Integer operateId) {
        repairOperateLogService.updateOperateResult(RepairResultEnum.FAILED, operateId);
        return ResultJson.success("执行成功");
    }

    /**
     * 查询某次修复的结果
     *
     * @param operateId
     * @return
     */
    @GetMapping(value = "history/detail")
    public ResultJson<List<RepairDetailLog>> getOperateDetail(@RequestParam("operateId") Integer operateId) {
        return ResultJson.success(repairDetailLogService.getOperateDetail(operateId));
    }

    /**
     * 导出详情记录
     * @param operateId
     * @param response
     */
    @GetMapping(value = "history/detail/export")
    public void exportExcel(@RequestParam("operateId") Integer operateId, HttpServletResponse response) {
        List<RepairDetailLog> operateDetail = repairDetailLogService.getOperateDetail(operateId);
        if (CollectionUtils.isEmpty(operateDetail)) {
            ResponseUtil.writeResult(response, ResultJson.fail("找不到详情记录"));
            return;
        }
        //转换excel格式
        List<RepairDetailDTO> collect = operateDetail.stream().map(repairDetailLog ->
                generateDTO(repairDetailLog)
        ).collect(Collectors.toList());
        RepairOperateLog operateLog = repairOperateLogService.getById(operateId);
        String date = CalendarUtil.getDateStr("yyyyMMdd", operateLog.getOperateDate());
        String fileName = String.format("报告模板_%s.xlsx", date);
        ExcelUtils.writeExcel(response, collect, RepairDetailDTO.class, fileName);
    }

    private RepairDetailDTO generateDTO(RepairDetailLog repairDetailLog) {
        String dateStr = CalendarUtil.getDateStr("yyyy年MM月dd日", repairDetailLog.getRepairDate());
        RepairStepResultEnum result = RepairStepResultEnum.getEnum(repairDetailLog.getOperateResult());
        String s = "";
        switch (result) {
            case FAILED:
                s = "失败，" + getErrorMsg(repairDetailLog);
                break;
            case SUCCESS:
                s = "成功";
                break;
            case INVOKING:
                s = "还在执行";
                break;
            case IDLE:
                s = "未开始";
                break;
        }
        return new RepairDetailDTO(dateStr, s);
    }

    private String getErrorMsg(RepairDetailLog repairDetailLog) {
        if (StringUtils.isNotEmpty(repairDetailLog.getOperateLog()))
            return repairDetailLog.getOperateLog();
        if (StringUtils.isNotEmpty(repairDetailLog.getRequestLog()))
            return repairDetailLog.getRequestLog();
        return "请查看日志";
    }

    /**
     * 查询修复列表
     *
     * @param repairLogQuery
     * @return
     */
    @PostMapping(value = "/history/query")
    public ResultJson<PageSimpleVO<RepairOperateLog>> historyQuery(@RequestBody @Valid RepairLogQuery repairLogQuery) {
        return ResultJson.success(repairOperateLogService.operateLogQuery(repairLogQuery));
    }

    /**
     * 是否是正确的日期, yyyy-MM-dd
     *
     * @param date
     * @return
     */
    private boolean isCorrectDate(String date) {
        return CalendarUtil.isAccurateDate(date, getDefaultDatePattern());
    }
}
